﻿// ===============================================================================
// RegexRule.cs
// EOS Framework
// ===============================================================================
// Copyright (c) EOS Development Group. All rights reserved.
// ===============================================================================

namespace EOS.Framework.Rules
{
    using System;
    using System.Text.RegularExpressions;
    using EOS.Framework.Tools;

    /// <summary>
    /// Makes validation through regular expression.
    /// </summary>
    public class RegexRule : Rule
    {
        /// <summary>
        /// Indicates, if the value can be empty.
        /// </summary>
        private bool canBeEmpty;

        /// <summary>
        /// The regular expression.
        /// </summary>
        private string regularExpression;

        /// <summary>
        /// Gets or sets the regular expression.
        /// </summary>
        /// <value>The regular expression. Cannot be null or empty and must 
        /// not contain only whitespaces.</value>
        /// <exception cref="ArgumentNullException"><paramref name="value"/> is
        /// null (Nothing in Visual Basic).</exception>
        /// <exception cref="ArgumentException"><paramref name="value"/> is
        /// a string of length 0 or contains only blanks.</exception>
        public string RegularExpression
        {
            get { return regularExpression; }
            set 
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }

                if (StringHelper.IsEmptyOrBlanksOnly(value))
                {
                    throw new ArgumentException(Properties.Resources.EmptyStringParameter, "value");
                }

                regularExpression = value; 
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RegexRule"/> class.
        /// </summary>
        /// <param name="description">The description.</param>
        /// <param name="regularExpression">The regular expression.</param>
        /// <exception cref="ArgumentNullException">
        /// 	<para><paramref name="description"/> is
        ///     null (Nothing in Visual Basic).</para>
        /// 	<para>- or -</para>
        /// 	<para><paramref name="regularExpression"/> is
        ///     null (Nothing in Visual Basic).</para>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 	<para><paramref name="description"/> is
        ///     a string of length 0 or contains only blanks.</para>
        /// 	<para>- or -</para>
        /// 	<para><paramref name="description"/> is
        ///     a string of length 0 or contains only blanks.</para>
        /// </exception>
        public RegexRule(string description, string regularExpression)
            : this(description, regularExpression, false)
        { }

        /// <summary>
        /// Initializes a new instance of the <see cref="RegexRule"/> class.
        /// </summary>
        /// <param name="description">The description.</param>
        /// <param name="regularExpression">The regular expression.</param>
        /// <param name="canBeEmpty">if set to <c>true</c> the value can be empty.</param>
        /// <exception cref="ArgumentNullException">
        /// 	<para><paramref name="description"/> is
        ///     null (Nothing in Visual Basic).</para>
        /// 	<para>- or -</para>
        /// 	<para><paramref name="regularExpression"/> is
        ///     null (Nothing in Visual Basic).</para>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 	<para><paramref name="description"/> is
        ///     a string of length 0 or contains only blanks.</para>
        /// 	<para>- or -</para>
        /// 	<para><paramref name="description"/> is
        ///     a string of length 0 or contains only blanks.</para>
        /// </exception>
        public RegexRule(string description, string regularExpression, bool canBeEmpty)
            : base(description)
        {
            if (regularExpression == null)
            {
                throw new ArgumentNullException("regularExpression");
            }

            if (StringHelper.IsEmptyOrBlanksOnly(regularExpression))
            {
                throw new ArgumentException(Properties.Resources.EmptyStringParameter, "regularExpression");
            }

            this.canBeEmpty = canBeEmpty;
            this.regularExpression = regularExpression;
        }


        /// <summary>
        /// Validates that the rule has been followed.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool Validate(object value)
        {
            string valueAsString = value as string;
            if (value == null || (valueAsString != null && StringHelper.IsEmptyOrBlanksOnly(valueAsString)))
            {
                return canBeEmpty == true;
            }

            return Regex.IsMatch(value.ToString(), regularExpression);
        }
    }
}
